package com.harmontronics.hanma.paas.paas.domain.job.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.harmontronics.hanma.paas.paas.consts.NumberEnum;
import com.harmontronics.hanma.paas.paas.consts.ScheduleConstants;
import com.harmontronics.hanma.paas.paas.domain.job.entity.JobListPage;
import com.harmontronics.hanma.paas.paas.domain.job.repository.persistence.HmJobRepository;
import com.harmontronics.hanma.paas.paas.domain.job.entity.HmJob;
import com.harmontronics.hanma.paas.paas.domain.job.service.helper.ScheduleUtil;
import org.quartz.JobDataMap;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.harmontronics.hanma.paas.paas.common.PageBase;

import com.harmontronics.hanma.paas.paas.domain.job.repository.mapper.HmJobMapper;
import com.harmontronics.hanma.paas.paas.domain.job.repository.po.HmJobPO;
import java.util.List;
import org.springframework.transaction.annotation.Transactional;

@Service("hmJobService")
@DS("#header.App-Unique")
public class HmJobService {

    @Autowired
    private HmJobRepository hmJobRepository;

    @Autowired
    private HmJobMapper hmJobMapper;

    @Autowired
    private Scheduler scheduler;


    public HmJob findById(String jobId) {
            HmJobPO po = hmJobRepository.getById(jobId);
        return BeanUtil.toBean(po,HmJob. class);
    }


    public void update(HmJob hmJob) {
            HmJobPO po = BeanUtil.toBean(hmJob,HmJobPO.class);
            hmJobRepository.updateById(po);
    }



    @Transactional(rollbackFor = Exception.class)
    public void saveJob(HmJob job) throws SchedulerException {
        job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
        job.setConcurrent(NumberEnum.ZERO.getNumStr());
        HmJobPO po = BeanUtil.toBean(job,HmJobPO.class);
        hmJobRepository.save(po);
        ScheduleUtil.createScheduleJob(scheduler, po);
    }


    @Transactional(rollbackFor = Exception.class)
    public void updateJob(HmJob job) throws SchedulerException {
        HmJob jobDb = this.findById(job.getJobId());
        this.update(job);
        updateSchedulerJob(job, jobDb.getJobGroup());
    }

    /**
     * 更新任务
     *
     * @param job      任务对象
     * @param jobGroup 任务组名
     */
    private void updateSchedulerJob(HmJob job, String jobGroup) throws SchedulerException {
        String jobId = job.getJobId();
        // 判断是否存在
        JobKey jobKey = ScheduleUtil.getJobKey(jobId, jobGroup);
        if (scheduler.checkExists(jobKey)) {
            // 防止创建时存在数据问题 先移除，然后在执行创建操作
            scheduler.deleteJob(jobKey);
        }
        HmJobPO po = BeanUtil.toBean(job,HmJobPO.class);
        ScheduleUtil.createScheduleJob(scheduler, po);
    }

    /**
     * 批量删除调度信息
     *

     */

    @Transactional(rollbackFor = Exception.class)
    public void delete(List<String> idList) throws SchedulerException {
        for (String jobId : idList) {
            HmJob job = this.findById(jobId);
            delete(job);
        }
    }

    /**
     * 删除任务后，所对应的trigger也将被删除
     *
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(HmJob job) throws SchedulerException {
        String jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        hmJobRepository.removeById(jobId);
        scheduler.deleteJob(ScheduleUtil.getJobKey(jobId, jobGroup));

    }


    /**
     * 任务调度状态修改
     *
     */
    @Transactional(rollbackFor = Exception.class)
    public void changeStatus(String jobId) throws SchedulerException {
        HmJob sysJob = this.findById(jobId);
        String status = sysJob.getStatus();
        if (ScheduleConstants.Status.NORMAL.getValue().equals(status)) {
            pause(sysJob);
        } else if (ScheduleConstants.Status.PAUSE.getValue().equals(status)) {
            resume(sysJob);
        }
    }

    /**
     * 暂停任务
     *
     * @param job 调度信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void pause(HmJob job) throws SchedulerException {
        String jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
        update(job);
        scheduler.pauseJob(ScheduleUtil.getJobKey(jobId, jobGroup));

    }

    /**
     * 恢复任务
     *
     * @param job 调度信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void resume(HmJob job) throws SchedulerException {
        String jobId = job.getJobId();
        String jobGroup = job.getJobGroup();
        job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
        update(job);
        scheduler.resumeJob(ScheduleUtil.getJobKey(jobId, jobGroup));

    }

    /**
     * 立即运行任务
     *
     */
    @Transactional(rollbackFor = Exception.class)
    public void run(String jobId) throws SchedulerException {
        HmJob sysJob = this.findById(jobId);
        String jobGroup = sysJob.getJobGroup();
        // 参数
        JobDataMap dataMap = new JobDataMap();
        dataMap.put(ScheduleConstants.TASK_PROPERTIES, sysJob);
        scheduler.triggerJob(ScheduleUtil.getJobKey(jobId, jobGroup), dataMap);
    }

    public PageBase<HmJob> getPageUserWithParams(JobListPage<HmJob> page){
        JobListPage<HmJob> jobPage = hmJobMapper.selectListWithParams(page);
        PageBase<HmJob> pageDto = new PageBase<>();
        pageDto.setData(jobPage.getRecords());
        pageDto.setPageNo((int) jobPage.getCurrent());
        pageDto.setPageSize((int) jobPage.getSize());
        pageDto.setTotalCount(jobPage.getTotal());
        pageDto.setTotalPage(jobPage.getPages());
        return pageDto;
    }



}